/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package admintool;

import admintool.imp03_data.IMP03_Candidate;
import admintool.imp03_data.IMP03_Experience;
import admintool.imp03_data.IMP03_Platform;
import admintool.imp03_data.IMP03_Skill;
import admintool.imp03_data.IMP03_Vacancy;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import javax.swing.JOptionPane;

/**
 *
 * @author Administrator
 */
public class MatchRatingCalculator {

    private IMP03_Candidate candidate = null;
    private IMP03_Vacancy vacancy = null;
    
    private int candidateVacancyMatch = 0;
    
    private int distanceFactor = 100; 
    private int skillFactor = 100; 
    private int qualificationFactor = 100; 
    private int experienceFactor = 100; 

    /**
     * 
     * @param candidate
     * @param vacancy
     */
    public MatchRatingCalculator(IMP03_Candidate candidate, IMP03_Vacancy vacancy) {
        this.candidate = candidate;
        this.vacancy = vacancy;
        
        candidateVacancyMatch = calculateCandidateVacancyMatch();
    }
    
    public int whichPlaceHasMyCandidateInComparisionToTheRest(IMP03_Platform selectedPlatform){
        int whichPlaceHasMyCandidate = 1;
        int highestPercentage = calculateCandidateVacancyMatch();

        ArrayList<IMP03_Candidate> tmpCandidates = IMP03_Candidate.getAllAvailableCandidatesForSpecificPlatform(selectedPlatform);
        for(IMP03_Candidate tmpCandidate : tmpCandidates){
            if(tmpCandidate.getCandidateID() != candidate.getCandidateID()){
                MatchRatingCalculator tmpMatchRatingCalculator = new MatchRatingCalculator(tmpCandidate, vacancy);
                if(tmpMatchRatingCalculator.getCandidateVacancyMatch() > highestPercentage){
                    whichPlaceHasMyCandidate++;
                }
            }
        }
        return whichPlaceHasMyCandidate;
    }
    
    private int calculateCandidateVacancyMatch(){
       //Calculate Experience-Factor
       int candidateExperience = 0;
       for(IMP03_Experience e : candidate.getCandidateExperience()){
           candidateExperience += e.getExperienceDurationInYears();
       }
       
       double experienceProportion = candidateExperience / vacancy.getVacancyExperienceInYears();
       if(experienceProportion >= 1.0) {
           experienceFactor = 100;
       } else if(experienceProportion >= 0.75) {
           experienceFactor = 75;
       } else if(experienceProportion >= 0.5) {
           experienceFactor = 50;
       } else if(experienceProportion >= 0.25) {
           experienceFactor = 25;
       } else {
           experienceFactor = 0;
       }
       
       //Calculate Distance-Factor between candidate and vacancy
       double distanceInKilometers = calculateDistance();
       System.out.println("DISTANCE = " + distanceInKilometers);
       if(distanceInKilometers < 50){
           distanceFactor = 100;
       } else if(distanceInKilometers < 100){
           distanceFactor = 75;
       } else if(distanceInKilometers < 200){
           distanceFactor = 50;
       } else if(distanceInKilometers < 300){
           distanceFactor = 25;
       } else {
           distanceFactor = 0;
       }
       
       //Calculate SkillLevel-Match
       int matchLevel1Skills = 0;
       int matchLevel2Skills = 0;
       int matchLevel3Skills = 0;
       
       int countLevel1Skills = 0;
       int countLevel2Skills = 0;
       int countLevel3Skills = 0;
       
       for(IMP03_Skill skill : vacancy.getVacancySkills()){
           //String skillName = skill.getSkillName();
           int vacancySkillLevel = skill.getSkillLevelForVacancy(vacancy.getVacancyID());
           int candidateSkillLevel = skill.getSkillLevelForCandidate(candidate.getCandidateID());
           
           if(vacancySkillLevel == 1){
               countLevel1Skills++;
               if(candidateSkillLevel == 1){
                   matchLevel1Skills += 100;
               } else if(candidateSkillLevel == 2){
                   matchLevel1Skills += 50;
               } if(candidateSkillLevel == 3){
                   matchLevel1Skills += 25;
               }
           } else if(vacancySkillLevel == 2){
               countLevel2Skills++;
               if(candidateSkillLevel == 1){
                   matchLevel2Skills += 100;
               } else if(candidateSkillLevel == 2){
                   matchLevel2Skills += 75;
               } if(candidateSkillLevel == 3){
                   matchLevel2Skills += 50;
               }
           } if(vacancySkillLevel == 3){
               countLevel3Skills++;
               if(candidateSkillLevel == 1){
                   matchLevel3Skills += 100;
               } else if(candidateSkillLevel == 2){
                   matchLevel3Skills += 100;
               } if(candidateSkillLevel == 3){
                   matchLevel3Skills += 75;
               }
           }
       }
       
       if((countLevel1Skills + countLevel2Skills + countLevel3Skills) > 0){
           int level1factor = 7;
           int level2factor = 2;
           int level3factor = 1;
           skillFactor = (level1factor * matchLevel1Skills + level2factor * matchLevel2Skills + level3factor * matchLevel3Skills) / (countLevel1Skills * level1factor  + countLevel2Skills * level2factor + countLevel3Skills * level3factor);
       }
           
       //Qualification
       // 1 = Doctor
       // 2 = Master
       // 3 = Bacherlor
       // 4 = High School
       // 5 = Aprediceship
       int qualificationDifference = candidate.getQualificationID() - vacancy.getQualificationID();
       if(qualificationDifference <= 0) {
           qualificationFactor = 100;
       } else if(qualificationDifference == 1) {
           qualificationFactor = 50;
       } else if(qualificationDifference == 2) {
           qualificationFactor = 25;
       } else {
           qualificationFactor = 0;
       }
       
       //return the calculated match-rating
       return (int) Math.round((0.1 * distanceFactor) + (0.4 * skillFactor) + (0.3 * qualificationFactor) + (0.2 * experienceFactor));
   }
       
    /**
     * 
     * @param plz1
     * @param plz2
     * @return
     */
    public double calculateDistance(){
        PreparedStatement ps = null;
        ResultSet rs = null;
        double distanceInKilometers = 0;
        
        try {
            ps = AdminToolView.getDBConnection().prepareStatement("SELECT Longitude, Latitude FROM city WHERE plz = ? OR plz = ?");
            ps.setString(1, candidate.getPLZ());
            ps.setString(2, vacancy.getVacancyPLZ());
            rs = ps.executeQuery();

            double origin_longitude = 0;
            double origin_latitude = 0;
            double destination_longitude = 0;
            double destination_latitude = 0;

            int counter = 1;

            while(rs.next()){
                if(counter == 1){
                    origin_longitude = Double.valueOf(rs.getString(1));
                    origin_latitude = Double.valueOf(rs.getString(2));
                } else if(counter == 2){
                    destination_longitude = Double.valueOf(rs.getString(1));
                    destination_latitude = Double.valueOf(rs.getString(2));
                }
                counter++;
            }

            origin_longitude = origin_longitude * Math.PI / 180;
            origin_latitude = origin_latitude * Math.PI / 180;
            destination_longitude = destination_longitude * Math.PI / 180;
            destination_latitude = destination_latitude * Math.PI / 180;

            //source of the data: http://opengeodb.giswiki.org/wiki/OpenGeoDB
            //logic: http://www.excelformeln.de/formeln.html?welcher=463
            //compare result to: http://www.postleitzahl.org/entfernung.html
            double radius = (6378137 + 6356751) / 2000;
            distanceInKilometers = radius * Math.acos(Math.sin(destination_latitude)*Math.sin(origin_latitude)+Math.cos(destination_latitude)*Math.cos(origin_latitude)*Math.cos(destination_longitude - origin_longitude));
        } catch (Exception e) {
            JOptionPane.showConfirmDialog(null, e.getMessage(), "Calculate Distance", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
            e.printStackTrace();
        } finally {
            try {
                if(ps != null){
                    ps.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        
        return distanceInKilometers;
   }

   /**
    * 
    * @return
    */
   public int getDistanceFactor() {
        return distanceFactor;
    }

    /**
     * 
     * @return
     */
    public int getExperienceFactor() {
        return experienceFactor;
    }

    /**
     * 
     * @return
     */
    public int getQualificationFactor() {
        return qualificationFactor;
    }

    /**
     * 
     * @return
     */
    public int getSkillFactor() {
        return skillFactor;
    }

    /**
     * 
     * @return
     */
    public int getCandidateVacancyMatch() {
        return candidateVacancyMatch;
    }
   
}
